home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / os2 / freetype.zip / raster.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-09-07  |  42.8 KB  |  1,812 lines

  1. {***************************************************************************}
  2. {*                                                                         *}
  3. {*    The Portable TrueType Engine - Copyright 1996 David TURNER           *}
  4. {*_________________________________________________________________________*}
  5. {*                                                                         *}
  6. {* Unit RASTER.PAS                                                         *}
  7. {*                                                                         *}
  8. {*  This unit is in charge of the final scanlin conversion to a bitmap     *}
  9. {*                                                                         *}
  10. {*  XXX : Cette version est sécurisée et fournit un sub-banding efficace   *}
  11. {*                                                                         *}
  12. {*        Reste à retirer la limite de 64(up)+64(down) profils simultanés  *}
  13. {*        ( Astuce : Calculer la taille des tables de tracé en fin de      *}
  14. {*                   parcours.. )                                          *}
  15. {*                                                                         *}
  16. {***************************************************************************}
  17.  
  18. Unit RASTER;
  19.  
  20. interface
  21.  
  22. {$DEFINE DEBUG}    (* Affiche par writeln les erreurs fatales du raster *)
  23.  
  24. { $DEFINE DEBUG2}  (* Trace le bloc inverse en fin de render *)
  25. { $DEFINE DEBUG3}  (* Trace les pixels pendant le render *)
  26. { $DEFINE DEBUG4}  (* Trace les profils plutôt que les pleins *)
  27.  
  28. {$DEFINE REVERSE} (* Autorise l'affichage des glyphes dont l'orientation *)
  29.                   (* est erronnée                                        *)
  30.  
  31. { $DEFINE CALCUL}
  32.  
  33. uses TTTypes,
  34.      TTCalc,
  35.      TTDisp;   (* This one only for debugging purpose *)
  36.  
  37. const
  38.   TTFlowDown  = -1; (* Indique un bitmap orienté de haut en bas *)
  39.   TTFlowUp    =  1; (* Indique un bitmap orienté de bas en haut *)
  40.   TTFlowError =  0; (* Indique une erreur lors du calcul        *)
  41.  
  42.   Err_Ras_None       =  0;
  43.   Err_Ras_NotIni     = -2;  { Rasterizer not Initialized   }
  44.   Err_Ras_Overflow   = -3;  { Profile Table Overflow       }
  45.   Err_Ras_Neg_H      = -4;  { Negativ Height encountered ! }
  46.   Err_Ras_Invalid    = -5;  { Invalid value encountered !  }
  47.  
  48.   TTDropOutControlNone     = 0;  { No Drop-out control                 }
  49.   TTDropOutControlSimple   = 1;  { Simple Drop-out control ( rule #3 ) }
  50.   TTDropOutControlComplex  = 2;  { Sophisticated control ( rule #4 )   }
  51.  
  52. type
  53.  
  54.   (* Cette structure permet de décrire le type du BitMap où seront  *)
  55.   (* rendus les glyphes                                             *)
  56.  
  57.   PRasterBlock = ^TRasterBlock;
  58.   TRasterBlock = record
  59.                    Rows   : ULong;        (* Nombre de lignes du bloc    *)
  60.                    Cols   : ULong;        (* Nombre de colonnes du bloc  *)
  61.                    Width  : ULong;        (* Nombre de pixels/ligne      *)
  62.                    Flow   : LongInt;      (* Définit l'orientation du    *)
  63.                                           (* bitmap                      *)
  64.                    Buffer : Pointer;      (* Pointeur vers le Buffer     *)
  65.                    Size   : ULong;        (* Taille du buffer            *)
  66.                  end;
  67.  
  68.  
  69.   (* Cette structure permet de décrire au rasterizer le glyphe que nous  *)
  70.   (* voulons rendre dans le BitMap                                       *)
  71.  
  72.   PGlyphRecord = ^TGlyphRecord;
  73.   TGlyphRecord = record
  74.                    Outlines  : ULong;      (* Nombre de contours du glyphe *)
  75.                    OutStarts : Pointer;    (* Indices de début de chaque   *)
  76.                                            (* contour                      *)
  77.                    Points    : ULong;      (* Nombre de points             *)
  78.                    XCoord    : Pointer;    (* Tableau des abscisses        *)
  79.                    YCoord    : Pointer;    (* Tableau des ordonnées        *)
  80.                    Flag      : Pointer;    (* Tableau des flags            *)
  81.                   end;
  82.  
  83. var
  84.   Rast_Err : Int;
  85.  
  86. function InitRasterizer( var rasterBlock : TRasterBlock;
  87.                              profBuffer  : PStorage;
  88.                              profSize    : ULong
  89.                         )
  90.                         : Int;
  91.  
  92. function RenderGlyph( var AGlyph : TGlyphRecord;
  93.                           xmax,
  94.                           ymax   : Int
  95.                     ) : boolean;
  96.  
  97. implementation
  98.  
  99.  
  100. const
  101.   MaxBezier  = 32;       (* Le nombre maximum de sous-arcs de Bezier *)
  102.   MaxProfils = 256;      (* Le nombre maximum de profils d'un glyphe *)
  103.  
  104.   Precision  = 64;               (* Precision sur 6 bits         *)
  105.   Precision2 = Precision div 2;  (* La moitié de notre précision *)
  106.  
  107.  
  108. type
  109.  
  110.   TEtats  = ( Indetermine, Ascendant, Descendant, Plat, Rupture );
  111.  
  112.   PTraceRec = ^TTraceRec;
  113.  
  114.   PProfil = ^TProfil;
  115.   TProfil = record
  116.               Flow   : Int;       (* Profil montant ou descendant  *)
  117.               Height : Int;       (* Hauteur du profil             *)
  118.               Start  : Int;       (* ordonnée de départ du profil  *)
  119.               Offset : ULong;     (* Offset de début du profil     *)
  120.  
  121.               Link   : PProfil;   (* Prochain profil de la liste   *)
  122.               Index  : Int;       (* Index dans le teableau de     *)
  123.                                   (* tracé                         *)
  124.               CountL : Int;       (* Nombre de lignes à compléter  *)
  125.                                   (* avant le début du tracé de    *)
  126.                                   (* ce profil                     *)
  127.               StartL : Int;       (* Première ligne du tracé       *)
  128.               Trace  : PTraceRec; (* Pointeur sur le tracé utilisé *)
  129.             end;
  130.  
  131.  
  132.   TBand = record
  133.             Y_Min : Int;
  134.             Y_Max : Int;
  135.           end;
  136.  
  137.   TTraceElement = record
  138.                    Profil : PProfil;   (* Profil de cette abscisse       *)
  139.                    X      : LongInt;   (* Abscisse sur la ligne courante *)
  140.                   end;
  141.  
  142.   PTraceArray = ^TTraceArray;
  143.   TTraceArray = Array[0..127] of TTraceElement;
  144.  
  145.   TTraceRec = record
  146.                N : Int;
  147.                T : PTraceArray;
  148.               end;
  149.  
  150.  
  151. const
  152.   AlignProfileSize = ( sizeOf(TProfil) + 3 ) div 4;
  153.   AlignTraceSize   = ( sizeOf(TTraceRec) + 3 ) div 4;
  154.  
  155. var
  156.   cProfil  : PProfil;    (* Profil Courant *)
  157.   fProfil  : PProfil;    (* Tête de la liste chaînée des profils *)
  158.   oProfil  : PProfil;    (* Old Profile                          *)
  159.   gProfil  : PProfil;    (* Last Profile in case of impact       *)
  160.  
  161.   nProfs   : Int;        (* Nombre courant de profils *)
  162.  
  163.   Etat     : TEtats;       (* Etat du trace *)
  164.  
  165.   Fresh    : Boolean;      (* Indique un profil neuf dont le champ 'START' *)
  166.                            (* doit être complété                           *)
  167.  
  168.   Joint    : Boolean;      (* Indique que le dernier arc est tombé pile
  169.                               sur une scanLine. Evite les doublons *)
  170.  
  171.   Buff     : PStorage;     (* Buffer Profils              *)
  172.   MaxBuff  : ULong;        (* Taille du buffer            *)
  173.   profCur  : ULong;        (* Curseur du Buffer Profils   *)
  174.  
  175.   Cible      : TRasterBlock; (* Description du Bitmap cible *)
  176.  
  177.   BCible     : PByteArray;   (* Buffer bitmap cible *)
  178.  
  179.   Band_Stack : array[1..16] of TBand;
  180.   Band_Top   : Int;
  181.  
  182.   Trace_Left,
  183.   Trace_Right : TTraceRec;
  184.  
  185.   TraceOfs : Int;      (* Offset courant du tracé dans le bitmap  *)
  186.   DebugOfs : Int;      (* Offset écrant pour le débogage du tracé *)
  187.  
  188.   Arcs     : Array[0..2*MaxBezier] of
  189.               record                   (* La pile de points qui permet  *)
  190.                X, Y : LongInt          (* de travailler sur les arcs de *)
  191.               end;                     (* Bézier                        *)
  192.  
  193.   CurArc   : Int;                      (* Taille de la pile             *)
  194.  
  195.   XCoord,
  196.   YCoord   : PStorage;
  197.  
  198.   Flags    : PByteArray;
  199.   Outs     : PShortArray;
  200.  
  201.   nPoints,
  202.   nContours : Int;
  203.  
  204.   LastX,
  205.   LastY,
  206.   MinY,
  207.   MaxY     : LongInt;
  208.  
  209.   DropOutControl : Byte;
  210.  
  211. {************************************************}
  212. {*                                              *}
  213. {* Pset :                                       *}
  214. {*                                              *}
  215. {*  Cette procédure sert au débogage            *}
  216. {*                                              *}
  217. {************************************************}
  218.  
  219. procedure PSet;
  220. var c : byte;
  221.     o : Int;
  222.     x : LongInt;
  223. begin
  224.   X := Buff^[profCur];
  225.  
  226.   with cProfil^ do
  227.    begin
  228.     case Flow of
  229.       TTFlowUp   : o := 80*(profCur-Offset+Start) + ( X div (Precision*8) );
  230.       TTFlowDown : o := 80*(Start-profCur+offset) + ( X div (Precision*8) );
  231.      end;
  232.     if o>0 then
  233.      begin
  234.       c := Vio^[o] or ( $80 shr ( (X div precision) and 7 ));
  235.       Vio^[o]:=c;
  236.      end
  237.    end;
  238.  
  239. end;
  240.  
  241. {$IFDEF DEBUG3}
  242. procedure ClearBand( y1, y2 : Int );
  243. var
  244.   Y : Int;
  245.   K : Word;
  246. begin
  247.   K := y1*80;
  248.   FillChar( Vio^[k], (y2-y1+1)*80, 0 );
  249. end;
  250. {$ENDIF}
  251.  
  252. {************************************************}
  253. {*                                              *}
  254. {* InitProfile :                                *}
  255. {*                                              *}
  256. {*                                              *}
  257. {*                                              *}
  258. {*                                              *}
  259. {************************************************}
  260.  
  261. procedure InitProfile;
  262. begin
  263.   cProfil         := PProfil( @Buff^[profCur] );
  264.   cProfil^.Offset := profCur;
  265.   nProfs          := 0;
  266. end;
  267.  
  268. {************************************************}
  269. {*                                              *}
  270. {* NewProfile :                                 *}
  271. {*                                              *}
  272. {*  Crée un nouveau profil                      *}
  273. {*                                              *}
  274. {************************************************}
  275.  
  276. function NewProfile( AEtat : TEtats ) : boolean;
  277. begin
  278.  
  279.   if fProfil = NIL then
  280.     begin
  281.       cProfil := PProfil( @Buff^[profCur] );
  282.       fProfil := cProfil;
  283.       inc( profCur, AlignProfileSize );
  284.     end;
  285.  
  286.   if profCur >= MaxBuff then
  287.     begin
  288.       Rast_Err   := Err_Ras_Overflow;
  289.       NewProfile := False;
  290.       exit;
  291.     end;
  292.  
  293.   with cProfil^ do
  294.     begin
  295.  
  296.       Case AEtat of
  297.  
  298.         Ascendant  : Flow := TTFlowUp;
  299.         Descendant : Flow := TTFlowDown;
  300.       else
  301. {$IFDEF DEBUG}
  302.         Writeln('ERREUR : Profil incohérent' );
  303.         Halt(30);
  304. {$ELSE}
  305.         NewProfile := False;
  306.         Rast_Err   := Err_Ras_Invalid;
  307.         exit;
  308. {$ENDIF}
  309.       end;
  310.  
  311.       Start  := 0;
  312.       Height := 0;
  313.       Offset := profCur;
  314.       Link   := nil;
  315.     end;
  316.  
  317.   if gProfil = nil then gProfil := cProfil;
  318.  
  319.   Etat  := AEtat;
  320.   Fresh := True;
  321.   Joint := False;
  322.  
  323.   NewProfile := True;
  324. end;
  325.  
  326.  
  327. {************************************************}
  328. {*                                              *}
  329. {* EndProfile :                                 *}
  330. {*                                              *}
  331. {*  Finalise le profil actuel                   *}
  332. {*                                              *}
  333. {************************************************}
  334.  
  335. function EndProfile : boolean;
  336. var
  337.   H : Int;
  338. begin
  339.   H := profCur - cProfil^.Offset;
  340.  
  341.   if H < 0 then
  342.     begin
  343.       EndProfile := False;
  344.       Rast_Err   := Err_Ras_Neg_H;
  345.       exit;
  346.     end;
  347.  
  348.   if H > 0 then
  349.     begin
  350.       cProfil^.Height := H;
  351.       cProfil         := PProfil( @Buff^[profCur] );
  352.  
  353.       inc( profCur, AlignProfileSize );
  354.       cProfil^.Height := 0;
  355.       cProfil^.Offset := profCur;
  356.       inc( nProfs );
  357.     end;
  358.  
  359.   if profCur >= MaxBuff then
  360.     begin
  361.       EndProfile := False;
  362.       Rast_Err   := Err_Ras_Overflow;
  363.       exit;
  364.     end;
  365.  
  366.   Joint := False;
  367.  
  368.   EndProfile := True;
  369. end;
  370.  
  371. {************************************************}
  372. {*                                              *}
  373. {* FinalizeProfileTable :                       *}
  374. {*                                              *}
  375. {*  Ajuste les liens de la table des profils    *}
  376. {*                                              *}
  377. {************************************************}
  378.  
  379. procedure FinalizeProfileTable;
  380. var
  381.   n : int;
  382.   p : PProfil;
  383. begin
  384.   n := nProfs;
  385.  
  386.   if n > 1 then
  387.     begin
  388.  
  389.       P := fProfil;
  390.  
  391.       while n > 1 do with P^ do
  392.         begin
  393.           Link := PProfil( @Buff^[ Offset + Height ] );
  394.           P    := Link;
  395.  
  396.           dec( n );
  397.         end;
  398.  
  399.       P^.Link := nil;
  400.  
  401.     end
  402.   else
  403.     fProfil := nil;
  404.  
  405. end;
  406.  
  407. {************************************************}
  408. {*                                              *}
  409. {* SplitBezier :                                *}
  410. {*                                              *}
  411. {*   Decompose un arc de Bezier en deux sous-   *}
  412. {*   arcs dans la pile.                         *}
  413. {*                                              *}
  414. {************************************************}
  415.  
  416. procedure SplitBezier;
  417. var
  418.   X1, Y1, X2, Y2 : LongInt;
  419. begin
  420.   with Arcs[CurArc+2] do begin x1:=x; y1:=y; end;
  421.   with Arcs[CurArc]   do begin x2:=x; y2:=y; end;
  422.  
  423.   with Arcs[CurArc+4] do begin x:=x1; y:=y1; end;
  424.   with Arcs[CurArc+1] do
  425.    begin
  426.     inc(x1,x); inc(y1,y);
  427.     inc(x2,x); inc(y2,y);
  428.    end;
  429.  
  430.   x1 := x1 div 2; x2 := x2 div 2;
  431.   y1 := y1 div 2; y2 := y2 div 2;
  432.  
  433.   with Arcs[CurArc+3] do begin x:=x1; y:=y1; end;
  434.   with Arcs[CurArc+1] do begin x:=x2; y:=y2; end;
  435.   with Arcs[CurArc+2] do
  436.    begin
  437.     x:=( x1+x2 ) div 2;
  438.     y:=( y1+y2 ) div 2;
  439.    end;
  440.  
  441.   Inc( CurArc,2);
  442. end;
  443.  
  444.  
  445.  
  446. {************************************************}
  447. {*                                              *}
  448. {* PushBezier :                                 *}
  449. {*                                              *}
  450. {*   Empile un arc de Bezier au sommet de la    *}
  451. {*   pile.                                      *}
  452. {*                                              *}
  453. {************************************************}
  454.  
  455. procedure PushBezier( x1, y1, x2, y2, x3, y3 : LongInt );
  456. begin
  457.   curArc:=0;
  458.  
  459.   with Arcs[CurArc+2] do begin x:=x1; y:=y1; end;
  460.   with Arcs[CurArc+1] do begin x:=x2; y:=y2; end;
  461.   with Arcs[ CurArc ] do begin x:=x3; y:=y3; end;
  462. end;
  463.  
  464.  
  465.  
  466.  
  467. {************************************************}
  468. {*                                              *}
  469. {* LineUp                                       *}
  470. {*                                              *}
  471. {*  Détermine les abscisses d'un segment        *}
  472. {*  ascendant et les stocke dans le buffer de   *}
  473. {*  profils.                                    *}
  474. {*                                              *}
  475. {************************************************}
  476.  
  477.  
  478. function LineUp( x1, y1, x2, y2 : LongInt ) : boolean;
  479. var
  480.   Dx, Dy               : LongInt;
  481.   e1, e2, f1, f2, size : Int;
  482.   Ix, Rx, Ax           : LongInt;
  483. begin
  484.   LineUp := True;
  485.  
  486.   Dx:=x2-x1; Dy:=y2-y1;
  487.  
  488.   if (Dy<=0) or (y2<MinY) or (y1>MaxY) then exit;
  489.  
  490.   if y1 < MinY then
  491.    begin
  492.     x1 := x1 + MulDiv( Dx, MinY-y1, Dy );
  493.     e1 := MinY div Precision;
  494.     f1 := 0;
  495.    end
  496.   else
  497.    begin
  498.     e1:= y1 div Precision;
  499.     f1:= y1 mod Precision;
  500.    end;
  501.  
  502.   if y2>MaxY then
  503.    begin
  504.     x2 := x2 + MulDiv( Dx, MaxY-y2, Dy );
  505.     e2 := MaxY div Precision;
  506.     f2 := 0;
  507.    end
  508.   else
  509.    begin
  510.     e2 := y2 div Precision;
  511.     f2 := y2 mod Precision;
  512.    end;
  513.  
  514.   if f1>0 then
  515.    if e1=e2 then exit
  516.     else
  517.      begin
  518.       x1 := x1 + MulDiv( Dx, Precision-f1, Dy );
  519.       e1 := e1 + 1;
  520.      end
  521.  
  522.   (* Ce test permet d'éliminer les doublons *)
  523.  
  524.   else
  525.    if Joint then begin dec( profCur ); Joint:=False; end;
  526.  
  527.  
  528.   if f2>0 then x2 := x2 + MulDiv( Dx, -f2, Dy )
  529.   else
  530.     Joint:=True;
  531.  
  532.   (* Indique qu'on est tombé pile sur une ScanLine, pour éviter *)
  533.   (* les doublons                                               *)
  534.  
  535.   (* On vérifie si le profil est neuf *)
  536.  
  537.   if Fresh then
  538.    begin
  539.     cProfil^.Start:=e1;
  540.     Fresh:=False;
  541.    end;
  542.  
  543.   (* Bon, on y va *)
  544.  
  545.   if Dx>0 then
  546.    begin
  547.  
  548.     Ix := (Precision*Dx) div Dy;
  549.     Rx := (Precision*Dx) mod Dy;
  550.     Ax := 0;
  551.     Dx := 1;
  552.    end
  553.   else
  554.    begin
  555.     Ix := -((Precision*-Dx) div Dy);
  556.     Rx := (Precision*-Dx) mod Dy;
  557.     Ax := 0;
  558.     Dx:=-1;
  559.    end;
  560.  
  561.   size := ( e2-e1 )+1;
  562.   if ( profCur + size >= MaxBuff ) then
  563.    begin
  564.      LineUp   := False;
  565.      Rast_Err := Err_Ras_Overflow;
  566.      exit;
  567.    end;
  568.  
  569.   Repeat
  570.  
  571.     Buff^[profCur] := x1;
  572.     {$IFDEF DEBUG3} Pset; {$ENDIF}
  573.     inc( profCur );
  574.  
  575.  
  576.     x1:=x1+Ix;
  577.     Ax:=Ax+Rx;
  578.     if Ax>=Dy then begin Ax:=Ax-Dy; Inc(x1, Dx ); end;
  579.     inc( e1 );
  580.  
  581.   Until e1>e2;
  582. end;
  583.  
  584.  
  585.  
  586. {************************************************}
  587. {*                                              *}
  588. {* LineDown                                     *}
  589. {*                                              *}
  590. {*  Détermine les abscisses d'un segment        *}
  591. {*  descendant et les store dans le buffer de   *}
  592. {*  profils.                                    *}
  593. {*                                              *}
  594. {************************************************}
  595.  
  596.  
  597. function LineDown( x1, y1, x2, y2 : LongInt ): boolean;
  598. var
  599.   Dx, Dy                : LongInt;
  600.   e1, e2, f1, f2, size  : Int;
  601.  
  602.   Ix, Rx, Ax            : LongInt;
  603. begin
  604.   LineDown := True;
  605.  
  606.   Dx:=x2-x1; Dy:=y2-y1;
  607.  
  608.   if (Dy>=0) or (y1<MinY) or (y2>MaxY) then exit;
  609.  
  610.   if y1>MaxY then
  611.    begin
  612.     x1 := x1 + MulDiv( Dx, MaxY-y1, Dy );
  613.     e1 := MaxY div Precision;
  614.     f1 := 0;
  615.    end
  616.   else
  617.    begin
  618.     e1:= y1 div Precision;
  619.     f1:= y1 mod Precision;
  620.    end;
  621.  
  622.   if y2<MinY then
  623.    begin
  624.     x2 := x2 + MulDiv( Dx, MinY-y2, Dy );
  625.     e2 := MinY div Precision;
  626.     f2 := 0;
  627.    end
  628.   else
  629.    begin
  630.     e2 := y2 div Precision;
  631.     f2 := y2 mod Precision;
  632.    end;
  633.  
  634.   if f1>0 then x1 := x1 + MulDiv( Dx, -f1, Dy )
  635.   else
  636.  
  637.   (* Ce test permet d'éviter des doublons *)
  638.  
  639.   if Joint then begin dec( profCur ); Joint:=False; end;
  640.  
  641.  
  642.   if f2>0 then
  643.    if e2=e1 then exit
  644.     else
  645.      begin
  646.       x2 := x2 + MulDiv( Dx, Precision-f2, Dy );
  647.       e2 := e2 + 1;
  648.      end
  649.     else
  650.      Joint:=True;
  651.  
  652.   (* Indique qu'on est tombé pile sur une ScanLine, pour éviter *)
  653.   (* les doublons                                               *)
  654.  
  655.   (* On vérifie si le profil est neuf *)
  656.  
  657.   If Fresh then
  658.    begin
  659.     cProfil^.Start:=e1;
  660.     Fresh:=False;
  661.    end;
  662.  
  663.   (* Bon, on y va *)
  664.  
  665.   if Dx<0 then
  666.    begin
  667.     Ix := -((Precision*-Dx) div -Dy);
  668.     Rx := (Precision*-Dx) mod -Dy;
  669.     Ax := 0;
  670.     Dx := -1;
  671.    end
  672.   else
  673.    begin
  674.     Ix := (Precision*Dx) div -Dy;
  675.     Rx :=   (Precision*Dx) mod -Dy;
  676.     Ax := 0;
  677.     Dx := 1;
  678.    end;
  679.  
  680.   Dy:=-Dy;
  681.  
  682.   size := ( e1-e2 )+1;
  683.   if ( profCur + size >= MaxBuff ) then
  684.    begin
  685.      LineDown := False;
  686.      Rast_Err := Err_Ras_Overflow;
  687.      exit;
  688.    end;
  689.  
  690.   Repeat
  691.  
  692.     Buff^[profCur] := x1;
  693.     {$IFDEF DEBUG3} Pset; {$ENDIF}
  694.     inc( profCur );
  695.  
  696.     x1:=x1+Ix;
  697.     Ax:=Ax+Rx;
  698.     if Ax>=Dy then begin Ax:=Ax-Dy; Inc(x1, Dx ); end;
  699.     dec( e1 );
  700.  
  701.   Until e1<e2;
  702. end;
  703.  
  704.  
  705. {************************************************}
  706. {*                                              *}
  707. {* BezierUp                                     *}
  708. {*                                              *}
  709. {*  Détermine les abscisses d'un arc de Bézier  *}
  710. {*  ascendant et les stocke dans le buffer de   *}
  711. {*  profils                                     *}
  712. {*                                              *}
  713. {* L'arc considéré est celui qui se trouve au   *}
  714. {* sommet courant de la pile. L'arc est dépilé  *}
  715. {* lorsque la routine rend la main.             *}
  716. {*                                              *}
  717. {************************************************}
  718.  
  719.  
  720. function BezierUp : boolean;
  721. var
  722.   x1, y1, x2, y2, e, e2, e0 : LongInt;
  723.   debArc, f1                : Int;
  724.  
  725. begin
  726.   BezierUp := True;
  727.  
  728.   y1:=Arcs[curArc+2].y;
  729.   y2:=Arcs[curArc].y;
  730.  
  731.   if ( y2 < MinY ) or ( y1 > MaxY ) then
  732.    begin
  733.     dec( curArc,2 );
  734.     exit;
  735.    end;
  736.  
  737.   e2 := Precision*(y2 div Precision);
  738.  
  739.   if e2 > MaxY then e2 := MaxY;
  740.  
  741.   e0 := MinY;
  742.  
  743.   if y1<MinY then e:=MinY
  744.   else
  745.    begin
  746.     e  := Precision*((y1+precision-1) div precision);
  747.     f1 := y1 mod Precision;
  748.     e0 := e;
  749.  
  750.     if f1=0 then
  751.      begin
  752.  
  753.       if Joint then begin dec(profCur); Joint:=False; end;
  754.       (* ^ Ce test permet d'éviter les doublons *)
  755.  
  756.       Buff^[profCur] := Arcs[curArc+2].x;
  757.       {$IFDEF DEBUG3} Pset; {$ENDIF}
  758.       inc( profCur );
  759.  
  760.  
  761.       (* Remarque au sujet du débordement de table :     *)
  762.       (*                                                 *)
  763.       (*  Nous savons déjà que profCur < MaxBuff, il     *)
  764.       (*  y a donc la place pour au moins 1 ordonnée     *)
  765.       (*  et nous n'avons pas besoin de faire le test    *)
  766.       (*  ici !                                          *)
  767.       (*                                                 *)
  768.  
  769.       e:=e+Precision;
  770.      end
  771.    end;
  772.  
  773.   if Fresh then
  774.    begin
  775.     cProfil^.Start:=e0 div precision;
  776.     Fresh:=False;
  777.    end;
  778.  
  779.   (* Dépassement de table ? *)
  780.   if ( profCur + (e2 - e) div Precision + 1 >= MaxBuff ) then
  781.     begin
  782.       BezierUp := False;
  783.       Rast_Err := Err_Ras_Overflow;
  784.       exit;
  785.     end;
  786.  
  787.   debArc := curArc;
  788.  
  789.   while ( curArc>=debArc ) and ( e<=e2 ) do
  790.    begin
  791.     Joint:=False;
  792.  
  793.     y2:=Arcs[CurArc].y;
  794.  
  795.     if y2=e then
  796.      begin
  797.       Joint:=True;
  798.  
  799.       Buff^[profCur] := Arcs[curArc].x;
  800.       {$IFDEF DEBUG3} Pset; {$ENDIF}
  801.       inc( profCur );
  802.  
  803.       e:=e+Precision;
  804.       dec( curArc, 2 );
  805.      end
  806.  
  807.     else
  808.      if y2<e then dec( curArc, 2 )
  809.  
  810.     else
  811.      begin
  812.       y1:=Arcs[curArc+2].y;
  813.  
  814.       if (y2-y1)<Precision2 then
  815.        begin
  816.         x1 := Arcs[curArc+2].x;
  817.         x2 := Arcs[curArc].x;
  818.  
  819.         Buff^[profCur] := x1 + MulDiv( x2-x1, e-y1, y2-y1 );
  820.         {$IFDEF DEBUG3} Pset; {$ENDIF}
  821.         inc( profCur );
  822.  
  823.         dec( curArc, 2 );
  824.         e:=e+Precision;
  825.        end
  826.  
  827.       else
  828.        SplitBezier;
  829.  
  830.      end;
  831.    end;
  832.  
  833.   curArc:=debArc-2;
  834.  
  835. end;
  836.  
  837.  
  838.  
  839. {************************************************}
  840. {*                                              *}
  841. {* BezierDown                                   *}
  842. {*                                              *}
  843. {*  Détermine les abscisses d'un arc de Bézier  *}
  844. {*  descendant et les store dans le buffer de   *}
  845. {*  profils                                     *}
  846. {*                                              *}
  847. {* L'arc considéré est celui qui se trouve au   *}
  848. {* sommet courant de la pile. L'arc est dépilé  *}
  849. {* lorsque la routine rend la main.             *}
  850. {*                                              *}
  851. {************************************************}
  852.  
  853.  
  854. function BezierDown : boolean;
  855. var
  856.   x1, y1, x2, y2, e, e0, e2 : LongInt;
  857.   f1, debArc                : Int;
  858.  
  859. begin
  860.   BezierDown := True;
  861.  
  862.   y1:=Arcs[curArc+2].y;
  863.   y2:=Arcs[curArc].y;
  864.  
  865.   if ( y1 < MinY ) or ( y2 > MaxY ) then
  866.    begin
  867.     dec( curArc,2 );
  868.     exit;
  869.    end;
  870.  
  871.   e2 := Precision*( (y2+Precision-1) div Precision );
  872.  
  873.   if e2 < MinY then e2 := MinY;
  874.  
  875.   e0 := MaxY;
  876.  
  877.   if y1 > MaxY then e := MaxY
  878.   else
  879.    begin
  880.     e  := Precision*(y1 div Precision);
  881.     f1 := y1 mod Precision;
  882.     e0 := e;
  883.  
  884.     if f1=0 then
  885.      begin
  886.       if Joint then begin dec( profCur ); Joint:=False; end;
  887.       (* ^ Ce test permet d'éviter les doublons *)
  888.  
  889.       Buff^[profCur] := Arcs[curArc+2].x;
  890.       {$IFDEF DEBUG3} Pset; {$ENDIF}
  891.       inc( profCur );
  892.  
  893.  
  894.       (* Remarque au sujet du débordement de table :     *)
  895.       (*                                                 *)
  896.       (*  Nous savons déjà que profCur < MaxBuff, il     *)
  897.       (*  y a donc la place pour au moins 1 ordonnée     *)
  898.       (*  et nous n'avons pas besoin de faire le test    *)
  899.       (*  ici !                                          *)
  900.       (*                                                 *)
  901.  
  902.       e := e-Precision;
  903.      end
  904.    end;
  905.  
  906.   if Fresh then
  907.    begin
  908.     cProfil^.Start:=e0 div Precision;
  909.     Fresh:=False;
  910.    end;
  911.  
  912.   if ( profCur + (e - e2) div Precision + 1 >= MaxBuff ) then
  913.     begin
  914.       Rast_Err   := Err_Ras_Overflow;
  915.       BezierDown := False;
  916.       exit;
  917.     end;
  918.  
  919.   debArc := curArc;
  920.  
  921.   while ( curArc>=debArc ) and ( e>=e2 ) do
  922.    begin
  923.     Joint:=False;
  924.  
  925.     y2:=Arcs[CurArc].y;
  926.  
  927.     if y2=e then
  928.      begin
  929.       Joint:=True;
  930.  
  931.       Buff^[profCur] := Arcs[curArc].x;
  932.       {$IFDEF DEBUG3} Pset; {$ENDIF}
  933.       inc( profCur );
  934.  
  935.       e:=e-Precision;
  936.       dec( curArc,2 );
  937.      end
  938.  
  939.     else
  940.      if y2>e then dec( curArc,2 )
  941.  
  942.     else
  943.      begin
  944.       y1:=Arcs[curArc+2].y;
  945.  
  946.       if (y1-y2)<Precision2 then
  947.        begin
  948.         x1 := Arcs[curArc+2].x;
  949.         x2 := Arcs[curArc].x;
  950.  
  951.         Buff^[profCur] := x1 + MulDiv( x2-x1, e-y1, y2-y1 );
  952.         {$IFDEF DEBUG3} Pset; {$ENDIF}
  953.         inc( profCur );
  954.  
  955.         dec( curArc,2 );
  956.         e:=e-Precision;
  957.        end
  958.  
  959.       else
  960.        SplitBezier;
  961.  
  962.      end;
  963.    end;
  964.  
  965.  curArc:=debArc-2;
  966.  
  967. end;
  968.  
  969.  
  970.  
  971. {************************************************}
  972. {*                                              *}
  973. {* LineTo                                       *}
  974. {*                                              *}
  975. {*  Injection d'une ligne lors du calcul des    *}
  976. {*  abscisses/ordonnées                         *}
  977. {*                                              *}
  978. {************************************************}
  979.  
  980. function LineTo( x, y : LongInt ) : boolean;
  981. begin
  982.   LineTo := False;
  983.  
  984.   case Etat of
  985.  
  986.     Indetermine : if y>lastY then
  987.                     if not NewProfile( Ascendant ) then exit else
  988.                   else
  989.                    if y<lastY then
  990.                     if not NewProfile( Descendant ) then exit;
  991.  
  992.     Ascendant   : if y<lastY then
  993.                    begin
  994.                     if not EndProfile or
  995.                        not NewProfile( Descendant ) then exit;
  996.                    end;
  997.  
  998.     Descendant  : if y>LastY then
  999.                    begin
  1000.                     if not EndProfile or
  1001.                        not NewProfile( Ascendant ) then exit;
  1002.                    end;
  1003.    end;
  1004.  
  1005.   Case Etat of
  1006.     Ascendant  : if not LineUp  ( LastX, LastY, X, Y ) then exit;
  1007.     Descendant : if not LineDown( LastX, LastY, X, Y ) then exit;
  1008.    end;
  1009.  
  1010.   LastX:=x;
  1011.   LastY:=y;
  1012.  
  1013.   LineTo := True;
  1014. end;
  1015.  
  1016.  
  1017.  
  1018. {************************************************}
  1019. {*                                              *}
  1020. {* BezierTo                                     *}
  1021. {*                                              *}
  1022. {*  Injection d'un arc de Bézier lors du calcul *}
  1023. {*  des abscisses/ordonnées                     *}
  1024. {*                                              *}
  1025. {************************************************}
  1026.  
  1027. function BezierTo( x, y, Cx, Cy : LongInt ) : boolean;
  1028. var
  1029.   y1, y2, y3, x3 : LongInt;
  1030.   Etat_Bez       : TEtats;
  1031. begin
  1032.   BezierTo := False;
  1033.  
  1034.   PushBezier( LastX, LastY, Cx, Cy, X, Y );
  1035.  
  1036.   while ( curArc>=0 ) do
  1037.    begin
  1038.     y1:=Arcs[curArc+2].y;
  1039.     y2:=Arcs[curArc+1].y;
  1040.     y3:=Arcs[curArc].y;
  1041.     x3:=Arcs[curArc].x;
  1042.  
  1043.     {* On détermine l'état du bézier courant *}
  1044.  
  1045.     if y1 = y2 then
  1046.      begin
  1047.  
  1048.       if y2 = y3 then Etat_Bez := Plat
  1049.       else
  1050.       if y2 > y3 then Etat_Bez := Descendant
  1051.       else
  1052.                       Etat_Bez := Ascendant;
  1053.      end
  1054.  
  1055.     else
  1056.     if y1 > y2 then
  1057.      begin
  1058.  
  1059.       if y2 >= y3 then Etat_Bez := Descendant
  1060.       else
  1061.                        Etat_Bez := Indetermine;
  1062.      end
  1063.  
  1064.     else
  1065.      begin
  1066.  
  1067.       if y2 <= y3 then Etat_Bez := Ascendant
  1068.       else
  1069.                        Etat_Bez := Indetermine;
  1070.      end;
  1071.  
  1072.  
  1073.     {* On agit en conséquence *}
  1074.  
  1075.     case Etat_Bez of
  1076.  
  1077.       Plat        : dec( curArc, 2 );
  1078.  
  1079.       Indetermine : SplitBezier;
  1080.  
  1081.     else
  1082.  
  1083.       if Etat <> Etat_Bez then
  1084.         begin
  1085.  
  1086.           if Etat <> Indetermine then
  1087.             if not EndProfile then exit;
  1088.  
  1089.           if not NewProfile( Etat_Bez ) then exit;
  1090.  
  1091.         end;
  1092.  
  1093.       case Etat of
  1094.  
  1095.         Ascendant  : if not BezierUp then exit;
  1096.         Descendant : if not BezierDown then exit;
  1097.  
  1098.       end;
  1099.  
  1100.     end;
  1101.    end;
  1102.  
  1103.   LastX:=x3;
  1104.   LastY:=y3;
  1105.  
  1106.   BezierTo := True;
  1107. end;
  1108.  
  1109.  
  1110.  
  1111. {************************************************}
  1112. {*                                              *}
  1113. {* CurveTo                                      *}
  1114. {*                                              *}
  1115. {*   Injection de plusieurs arcs de Béziers     *}
  1116. {*                                              *}
  1117. {************************************************}
  1118.  
  1119. function CurveTo( x, y : LongInt; FirstCtrl, LastCtrl : Int ) : boolean;
  1120. var
  1121.   NextCtrl       : Int;
  1122.   xz, yz, cx, cy : LongInt;
  1123. begin
  1124.  
  1125.   CurveTo := False;
  1126.  
  1127.   NextCtrl := FirstCtrl+1;
  1128.  
  1129.   xz := XCoord^[FirstCtrl];
  1130.   yz := YCoord^[FirstCtrl];
  1131.  
  1132.   while FirstCtrl <= LastCtrl do
  1133.    begin
  1134.  
  1135.     if NextCtrl <= LastCtrl then
  1136.      begin
  1137.       cx := ( xz + XCoord^[NextCtrl] ) div 2;
  1138.       cy := ( yz + YCoord^[NextCtrl] ) div 2;
  1139.      end
  1140.  
  1141.     else
  1142.      begin
  1143.       cx := x;
  1144.       cy := y;
  1145.      end;
  1146.  
  1147.     if not BezierTo( cx, cy, xz, yz ) then exit;
  1148.  
  1149.     xz := XCoord^[NextCtrl];
  1150.     yz := YCoord^[NextCtrl];
  1151.  
  1152.     inc( FirstCtrl );
  1153.     inc( NextCtrl  );
  1154.    end;
  1155.  
  1156.   CurveTo := True;
  1157.  
  1158. end;
  1159.  
  1160.  
  1161. {************************************************}
  1162. {*                                              *}
  1163. {* ConvertGlyph                                 *}
  1164. {*                                              *}
  1165. {*  Effectue la conversion d'un glyphe en un    *}
  1166. {*  ensemble de profils.                        *}
  1167. {*                                              *}
  1168. {************************************************}
  1169.  
  1170. Function ConvertGlyph( _xCoord, _yCoord : PStorage ) : boolean;
  1171. var
  1172.   i, j, First, Last, Start : Int;
  1173.  
  1174.   y1, y2, y3 :  LongInt;
  1175.  
  1176. begin
  1177.   ConvertGlyph := False;
  1178.  
  1179.   j       := 0;
  1180.   nProfs  := 0;
  1181.   fProfil := NIL;
  1182.   Joint   := False;
  1183.   Fresh   := False;
  1184.  
  1185.   XCoord := _XCoord;
  1186.   YCoord := _YCoord;
  1187.  
  1188.   InitProfile;
  1189.  
  1190.   for i:=0 to nContours-1 do
  1191.    begin
  1192.  
  1193.     Etat    := Indetermine;
  1194.     First   := j;
  1195.     LastX   := xCoord^[j];
  1196.     LastY   := yCoord^[j];
  1197.     Start   := 0;
  1198.     gProfil := nil;
  1199.  
  1200.     inc(j);
  1201.  
  1202.     while j <= Outs^[i] do
  1203.      begin
  1204.  
  1205.       if Flags^[j] and 1 = 0 then  (* OFF Curve *)
  1206.  
  1207.         if Start=0 then
  1208.           begin
  1209.            Start := j;
  1210.            Last  := j;
  1211.           end
  1212.          else
  1213.           inc( Last )
  1214.  
  1215.       else                     (* ON Curve *)
  1216.        if Start<>0 then
  1217.         begin
  1218.          if not CurveTo( XCoord^[j], YCoord^[j], Start, Last ) then exit;
  1219.          Start:=0;
  1220.         end
  1221.        else
  1222.          if not LineTo( XCoord^[j], YCoord^[j] ) then exit;
  1223.  
  1224.       inc(j);
  1225.      end;
  1226.  
  1227.     if Start<>0 then
  1228.       if not CurveTo( XCoord^[First], YCoord^[First], Start, Last )
  1229.           then exit else
  1230.      else
  1231.       if not LineTo( XCoord^[First], YCoord^[First] ) then exit;
  1232.  
  1233.  
  1234.     (* Nous devons maintenant vérifier que les deux arcs extrémités ne se *)
  1235.     (* rejoignent pas.                                                    *)
  1236.  
  1237.     if ( lastY and (Precision-1) = 0 ) and
  1238.        ( lastY >= MinY ) and
  1239.        ( lastY <= MaxY ) then
  1240.  
  1241.       if ( gProfil <> nil ) and                  (* gProfil can be nil    *)
  1242.          ( gProfil^.Flow = cProfil^.Flow ) then  (* if the contour was    *)
  1243.                                                  (* too small to be drawn *)
  1244.            dec( profCur );
  1245.  
  1246.     if not EndProfile then exit;
  1247.    end;
  1248.  
  1249.   FinalizeProfileTable;
  1250.  
  1251.   ConvertGlyph := True;
  1252. end;
  1253.  
  1254.  
  1255. {************************************************}
  1256. {*                                              *}
  1257. {* RenderGlyph                                  *}
  1258. {*                                              *}
  1259. {*  cette fonction est temporaire, elle         *}
  1260. {*  permet surtout de tester et debugger l'unité*}
  1261. {*                                              *}
  1262. {*                                              *}
  1263. {************************************************}
  1264.  
  1265.   procedure Pixel( x,y : Int );
  1266.   var c : byte;
  1267.       o : int;
  1268.   begin
  1269.     if (x<0) or (x>=Cible.Width) or
  1270.        (y<0) or (y>=Cible.Rows) then exit;
  1271.  
  1272.     o := Cible.Cols*y + (x shr 3);
  1273.     c := PByteArray( Cible.Buffer )^[o];
  1274.     c := c or ( $80 shr (x and 7) );
  1275.  
  1276.   {$IFDEF DEBUG2}
  1277.     Vio^[ 80*y + (x shr 3) ]:=c;
  1278.   {$ENDIF}
  1279.  
  1280.     PByteArray(Cible.Buffer)^[o]:=c;
  1281.   end;
  1282.  
  1283.  
  1284.   procedure InsNew( Traces : PTraceRec;
  1285.                     Profil : PProfil;
  1286.                     X      : LongInt
  1287.                   );
  1288.   var
  1289.     I, J : Int;
  1290.   begin
  1291.     I:=0;
  1292.     with Traces^ do
  1293.      begin
  1294.        while ( I < N ) and ( T^[i].X <= X ) do inc(i);
  1295.        if i<N then
  1296.          for j:=N-1 downto i do
  1297.            begin
  1298.              T^[j+1]               := T^[j];
  1299.              T^[j+1].Profil^.Index := j+1;
  1300.            end;
  1301.        T^[i].Profil  := Profil;
  1302.        T^[i].X       := X;
  1303.        Profil^.Index := i;
  1304.  
  1305.        inc( N );
  1306.      end
  1307.   end;
  1308.  
  1309.  
  1310.   procedure DelOld( Traces : PTraceRec;
  1311.                     Index  : Int
  1312.                   );
  1313.   var
  1314.     I : Int;
  1315.   begin
  1316.     with Traces^ do
  1317.      begin
  1318.        T^[Index].Profil^.Index:=-1;
  1319.  
  1320.        for I:=Index to N-2 do
  1321.         begin
  1322.          T^[i]               := T^[i+1];
  1323.          T^[i].Profil^.Index := i;
  1324.         end;
  1325.        dec( N );
  1326.      end
  1327.   end;
  1328.  
  1329.  
  1330.   procedure Sort0( var Trace : TTraceRec );
  1331.   var
  1332.     I, J : Int;
  1333.     K    : LongInt;
  1334.     Q    : PProfil;
  1335.   begin
  1336.    with Trace do
  1337.  
  1338.     for I:=1 to N-1 do
  1339.  
  1340.      for J:=I downto 1 do
  1341.  
  1342.       if T^[j].X < T^[j-1].X then
  1343.        begin
  1344.  
  1345.         k         := T^[j-1].x;
  1346.         T^[j-1].x := T^[ j ].x;
  1347.         T^[ j ].x := k;
  1348.  
  1349.         Q              := T^[j-1].Profil;
  1350.         T^[j-1].Profil := T^[ j ].Profil;
  1351.         T^[ j ].Profil := Q;
  1352.  
  1353.         T^[j-1].Profil^.Index := j-1;
  1354.         Q^.Index              := j;
  1355.  
  1356.        end;
  1357.   end;
  1358.  
  1359.   procedure Sort( var Trace : TTraceRec );
  1360.   var
  1361.     I, J : Int;
  1362.     K, L : LongInt;
  1363.     Q    : PProfil;
  1364.   begin
  1365.  
  1366.    K := Trace.T^[0].X;
  1367.  
  1368.    with Trace do
  1369.  
  1370.     for I:=1 to N-1 do
  1371.  
  1372.     begin
  1373.  
  1374.      L := T^[i].X;
  1375.  
  1376.      if K > L then
  1377.  
  1378.        begin
  1379.  
  1380.          for I:=1 to N-1 do
  1381.           for J:=I downto 1 do
  1382.  
  1383.            if T^[j].X < T^[j-1].X then
  1384.             begin
  1385.  
  1386.              k         := T^[j-1].x;
  1387.              T^[j-1].x := T^[ j ].x;
  1388.              T^[ j ].x := k;
  1389.  
  1390.              Q              := T^[j-1].Profil;
  1391.              T^[j-1].Profil := T^[ j ].Profil;
  1392.              T^[ j ].Profil := Q;
  1393.  
  1394.              T^[j-1].Profil^.Index := j-1;
  1395.              Q^.Index              := j;
  1396.  
  1397.             end;
  1398.          exit;
  1399.        end
  1400.      else
  1401.        K := L;
  1402.     end
  1403.   end;
  1404.  
  1405.  
  1406. function DrawGlyph : boolean;
  1407.  
  1408. const
  1409.   LMask : array[0..7] of Byte
  1410.         = ($FF,$7F,$3F,$1F,$0F,$07,$03,$01);
  1411.  
  1412.   RMask : array[0..7] of Byte
  1413.         = ($80,$C0,$E0,$F0,$F8,$FC,$FE,$FF);
  1414. label
  1415.   No_Draw;
  1416.  
  1417. var
  1418.   y, k,
  1419.   I, J   : Int;
  1420.   P, Q   : PProfil;
  1421.  
  1422.   min_Y,
  1423.   max_Y  : Int;
  1424.  
  1425.   e1, e2,
  1426.   x1, x2 : LongInt;
  1427.  
  1428.   c1, c2 : Int;
  1429.   f1, f2 : Int;
  1430.  
  1431. begin
  1432.  
  1433.   DrawGlyph := False;
  1434.  
  1435.   {* On repère d'abord le minimum et le maximum des Y *}
  1436.  
  1437.   P     := fprofil;
  1438.   max_Y := MinY div Precision;
  1439.   min_Y := MaxY div Precision;
  1440.  
  1441.   while P<>NIL do
  1442.    with P^ do
  1443.     begin
  1444.      Case Flow of
  1445.  
  1446.        TTFlowUp : begin
  1447.                    if min_Y > Start          then min_Y := Start;
  1448.                    if max_Y < Start+Height-1 then max_Y := Start+height-1;
  1449.  
  1450.                    StartL := Start;
  1451.                    Index  := -1;
  1452.                    Trace  := @Trace_Left;
  1453.                   end;
  1454.  
  1455.        TTFlowDown : begin
  1456.                      if min_Y > Start-Height+1 then min_Y := Start-Height+1;
  1457.                      if max_Y < Start          then max_Y := Start;
  1458.  
  1459.                      StartL := Start-Height+1;
  1460.                      Offset := Offset+Height-1;
  1461.                      Index  := -1;
  1462.                      Trace  := @Trace_Right;
  1463.                     end;
  1464.       else
  1465.         (* Severe Error here !! *)
  1466.         Rast_Err := Err_Ras_Invalid;
  1467.         exit;
  1468.       end;
  1469.  
  1470.      P := Link;
  1471.    end;
  1472.  
  1473.   {* On calcule la distance au minimum de chaque profil *}
  1474.  
  1475.   P := fProfil;
  1476.  
  1477.   while P<>NIL do
  1478.    with P^ do
  1479.     begin
  1480.      CountL := (StartL-min_Y)+1;
  1481.      P      := Link;
  1482.     end;
  1483.  
  1484.   {* On se prépare encore un peu avant le grand saut *}
  1485.  
  1486.   TraceOfs := Cible.Cols * min_Y;
  1487.  
  1488.   Trace_Right.N := 0;
  1489.   Trace_Left.N  := 0;
  1490.  
  1491.   {* On y va *}
  1492.  
  1493.   for y := min_Y to max_Y do
  1494.    begin
  1495.  
  1496.     P := fProfil;
  1497.  
  1498.     while P<>NIL do
  1499.      with P^ do
  1500.  
  1501.      begin
  1502.  
  1503.       if CountL > 0 then
  1504.        begin
  1505.          dec( CountL );
  1506.          if CountL = 0 then
  1507.           begin
  1508.            InsNew( Trace, P, Buff^[Offset] );
  1509.            inc( Offset, Flow );
  1510.            dec( Height );
  1511.           end
  1512.        end
  1513.  
  1514.       else
  1515.        if CountL = 0 then
  1516.         begin
  1517.          Trace^.T^[Index].X := Buff^[Offset];
  1518.          inc( Offset, Flow );
  1519.          dec( Height );
  1520.         end;
  1521.  
  1522.       P:=Link;
  1523.      end;
  1524.  
  1525.     {* Maintenant, on trie *}
  1526.  
  1527.     Sort( Trace_Left );
  1528.     Sort( Trace_Right );
  1529.  
  1530.     {* Puis on trace *}
  1531.  
  1532.     i := 0;
  1533.  
  1534.     while ( i < Trace_Left.N ) do
  1535.      begin
  1536.  
  1537.       x1 := Trace_Left.T ^[i].X;
  1538.       x2 := Trace_Right.T^[i].X;
  1539.  
  1540. {$IFDEF REVERSE}
  1541.       if x1 > x2 then
  1542.         begin
  1543.           e1 := x1;
  1544.           x1 := x2;
  1545.           x2 := e1;
  1546.         end;
  1547. {$ENDIF}
  1548.  
  1549.       e1 := ( x1+63 ) and -64;
  1550.       e2 := x2 and -64;
  1551.  
  1552.       (* Drop-out control *)
  1553.  
  1554.       if e1 > e2 then
  1555.        if e1 = e2+1 then
  1556.         case DropOutControl of
  1557.  
  1558.           0 : goto No_Draw;
  1559.  
  1560.  
  1561.           (* Drop-out Control Rule #3 *)
  1562.           1 : e2 := e1;
  1563.  
  1564.           (* Drop-out Control Rule #4 *)
  1565.           2 : begin
  1566.                P := Trace_Left.T ^[i].Profil;
  1567.                Q := Trace_Right.T^[i].Profil;
  1568.  
  1569.                if ( P^.Height <= 0 ) or ( Q^.Height <= 0 )
  1570.                  then goto No_Draw;
  1571.  
  1572.                if ( y<=P^.StartL ) or ( y<=Q^.StartL )
  1573.                  then goto No_Draw;
  1574.  
  1575.                e2:=e1;
  1576.               end;
  1577.         end
  1578.        else
  1579.         goto No_Draw;
  1580.  
  1581.       e1 := e1 div Precision;
  1582.       e2 := e2 div Precision;
  1583.  
  1584.       if ( e2 >= 0 ) and ( e1 < Cible.Width ) then
  1585.         begin
  1586.  
  1587.           if e1 <  0 then e1 := 0;
  1588.           if e2 >= Cible.Width then e2 := Cible.Width-1;
  1589.  
  1590.           c1 := e1 shr 3;
  1591.           c2 := e2 shr 3;
  1592.  
  1593.           f1 := e1 and 7;
  1594.           f2 := e2 and 7;
  1595.  
  1596.           j := TraceOfs + c1;
  1597.  
  1598.           if c1 = c2 then
  1599.             BCible^[j] := BCible^[j] or ( LMask[f1] and Rmask[f2] )
  1600.           else
  1601.            begin
  1602.              BCible^[j] := BCible^[j] or LMask[f1];
  1603.  
  1604.              if c2>c1+1 then
  1605.                FillChar( BCible^[j+1], c2-c1-1, $FF );
  1606.  
  1607.              inc( j, c2-c1 );
  1608.  
  1609.              BCible^[j] := BCible^[j] or RMask[f2];
  1610.  
  1611.            end
  1612.         end;
  1613.  
  1614.      No_Draw:
  1615.  
  1616.        inc(i);
  1617.  
  1618.      end;
  1619.  
  1620.  
  1621.     {* Et enfin, on finalise les tracés *}
  1622.  
  1623.     inc( TraceOfs, Cible.Cols );
  1624.     inc( DebugOfs, 80 );
  1625.  
  1626.     P := fProfil;
  1627.  
  1628.     while P<>NIL do
  1629.      with P^ do
  1630.       begin
  1631.  
  1632.        if (CountL=0) and (Height=0) then
  1633.         begin
  1634.          DelOld( Trace, P^.Index );
  1635.          Height:=-1;
  1636.          CountL:=-1;
  1637.         end;
  1638.  
  1639.        P := Link;
  1640.       end;
  1641.    end;
  1642.  
  1643.   DrawGlyph := True;
  1644.  
  1645. end;
  1646.  
  1647.  
  1648.  
  1649. function RenderGlyph( var AGlyph      : TGlyphRecord;
  1650.                           xmax,
  1651.                           ymax        : Int ) : boolean;
  1652. var
  1653.   i, j, k : Int;
  1654.   P       : PProfil;
  1655.   profIni : Int;
  1656. begin
  1657.  
  1658.  RenderGlyph := False;
  1659.  
  1660.  if Buff = nil then
  1661.    begin
  1662.      Rast_Err := Err_Ras_NotIni;
  1663.      exit;
  1664.    end;
  1665.  
  1666.  Outs     := AGlyph.OutStarts;
  1667.  Flags    := Aglyph.Flag;
  1668.  nPoints  := AGlyph.Points;
  1669.  nContours:= AGlyph.Outlines;
  1670.  
  1671.  Rast_Err := Err_Ras_None;
  1672.  
  1673.  I := 64 * sizeof(TTraceRec);
  1674.  
  1675.  profCur:= ( 2*I + 3 ) div 4;
  1676.  
  1677.  Trace_Left.T  := PTraceArray( Buff );
  1678.  Trace_Right.T := PTraceArray( @Buff^[(I+3) div 4] );
  1679.  
  1680.  profIni := profCur;
  1681.  
  1682.  Band_Top            := 1;
  1683.  Band_Stack[1].Y_Min := 0;
  1684.  Band_Stack[1].Y_Max := Cible.Rows-1;
  1685.  
  1686.  BCible := PByteArray( Cible.Buffer );
  1687.  
  1688.  while Band_Top > 0 do
  1689.  
  1690.    begin
  1691.  
  1692.      with Band_Stack[ Band_Top ] do
  1693.        begin
  1694.          MaxY   := Y_Max * Precision;
  1695.          MinY   := Y_Min * Precision;
  1696.        end;
  1697.  
  1698.      profCur  := profIni;
  1699.      Rast_Err := Err_Ras_None;
  1700.  
  1701.      if not ConvertGlyph( AGlyph.XCoord, AGlyph.YCoord ) then
  1702.        begin
  1703.  
  1704.          (* sub-banding *)
  1705.  
  1706.          {$IFDEF DEBUG3}
  1707.          ClearBand( MinY div Precision, MaxY div Precision );
  1708.          {$ENDIF}
  1709.  
  1710.          with Band_Stack[Band_Top] do
  1711.            begin
  1712.              I := Y_Min;
  1713.              J := Y_Max;
  1714.            end;
  1715.  
  1716.          K := ( I + J ) div 2;
  1717.  
  1718.          if ( Band_Top >= 8 ) or ( K <= I ) then
  1719.            begin
  1720.              Band_Top := 0;
  1721.              Rast_Err := Err_Ras_Invalid;
  1722.              exit;
  1723.            end
  1724.          else
  1725.            begin
  1726.  
  1727.              with Band_Stack[Band_Top+1] do
  1728.                begin
  1729.                  Y_Min := K;
  1730.                  Y_Max := J;
  1731.                end;
  1732.  
  1733.              Band_Stack[Band_Top].Y_Max := K-1;
  1734.  
  1735.              inc( Band_Top );
  1736.            end
  1737.        end
  1738.      else
  1739.        begin
  1740.          if ( fProfil <> nil ) then
  1741.          {$IFDEF CALCUL}
  1742.            begin end;
  1743.          {$ELSE}
  1744.            if not DrawGlyph then exit;
  1745.          {$ENDIF}
  1746.          dec( Band_Top );
  1747.        end;
  1748.  
  1749.    end;
  1750.  
  1751.  RenderGlyph := True;
  1752.  exit;
  1753.  
  1754. {$IFNDEF DEBUG4}
  1755.  DrawGlyph;
  1756.  
  1757. {$ELSE}
  1758.  P:=fProfil;
  1759.  while P<>NIL do
  1760.   begin
  1761.    with P^ do
  1762.     case Flow of
  1763.  
  1764.       TTFlowUp   : for j:=0 to Height-1 do
  1765.                     Pixel( ( Buff^[Offset+j]+Precision-1 ) div Precision,
  1766.                            Start+j );
  1767.  
  1768.       TTFlowDown : for j:=0 to Height-1 do
  1769.                     Pixel( Buff^[Offset+j] div Precision,
  1770.                            Start-j );
  1771.     end;
  1772.    P:=P^.Link;
  1773.   end;
  1774. {$ENDIF}
  1775.  
  1776. end;
  1777.  
  1778.  
  1779. {************************************************}
  1780. {*                                              *}
  1781. {* InitRasterizer                               *}
  1782. {*                                              *}
  1783. {*  Initialisation du Rasterizer.               *}
  1784. {*  Récupère les adresses de la description du  *}
  1785. {*  BitMap et du buffer de profils, ainsi que   *}
  1786. {*  la taille de ce dernier.                    *}
  1787. {*                                              *}
  1788. {************************************************}
  1789.  
  1790. function InitRasterizer( var rasterBlock : TRasterBlock;
  1791.                              profBuffer  : PStorage;
  1792.                              profSize    : ULong
  1793.                         )
  1794.                         : Int;
  1795. begin
  1796.   Buff    := profBuffer;
  1797.   MaxBuff := (profSize div 4) - AlignProfileSize;
  1798.   Cible   := rasterBlock;
  1799.  
  1800.   DropOutControl := 2;
  1801.   Rast_Err       := Err_Ras_None;
  1802.  
  1803.   InitRasterizer := 0;
  1804. end;
  1805.  
  1806.  
  1807. begin
  1808.   MaxBuff := 0;
  1809.   Buff    := nil;
  1810.   profCur := 0;
  1811. end.
  1812.